package com.braincookie.plugins.jira.tabpanels;

import com.atlassian.jira.plugin.TabPanelModuleDescriptor;
import com.atlassian.jira.plugin.browsepanel.TabPanel;
import com.atlassian.jira.project.browse.BrowseContext;
import com.braincookie.plugins.jira.tabpanels.fragments.FilterTabPanelFragment;

import org.apache.commons.lang.StringUtils;

import java.util.Collections;
import java.util.List;

/**
 * Abstract base for {@link TabPanel} implementers to extend.  This looks
 * after the layout of all the fragments on the page and delegates content to the
 * {@link com.atlassian.jira.plugin.projectpanel.fragment.ProjectTabPanelFragment}.
 *
 * @since v4.0
 */
public abstract class AbstractFragmentBasedFilterTabPanel<D extends TabPanelModuleDescriptor, C extends BrowseContext, F extends FilterTabPanelFragment> implements TabPanel<D, C>
{
    protected D moduleDescriptor;

    public void init(final D descriptor)
    {
        this.moduleDescriptor = descriptor;
    }

    public String getHtml(final C ctx)
    {
        final StringBuilder sb = new StringBuilder();
        String inlineHeader = getInlineHeader();


        if (StringUtils.isNotBlank(inlineHeader))
        {
            sb.append("<h2>" + inlineHeader + "</h2>");
        }
        
        createContent(ctx, sb);
        return sb.toString();
    }

    public String getInlineHeader()
    {
        return null;
    }

    private void createContent(C ctx, StringBuilder sb)
    {
        final StringBuilder leftcolSb = new StringBuilder();
        final boolean hasLeftContent = createColumnContent(ctx, leftcolSb, getLeftColumnFragments(ctx));

        final StringBuilder rightcolSb = new StringBuilder();
        final boolean hasRightContent = createColumnContent(ctx, rightcolSb, getRightColumnFragments(ctx));

        final StringBuilder topSb = new StringBuilder();
        final boolean hasTopContent = createColumnContent(ctx, topSb, getTopFragments(ctx));

        if (hasTopContent)
        {
            sb.append("<div class=\"aui-group\">");
            sb.append("<div class=\"aui-item\">");
            sb.append(topSb);
            sb.append("</div>");
            sb.append("</div>");
        }

        if (hasLeftContent && hasRightContent)
        {
            sb.append("<div class=\"aui-group\">");
            sb.append("<div class=\"aui-item\">");
            sb.append(leftcolSb);
            sb.append("</div>");
            sb.append("<div class=\"aui-item\">");
            sb.append(rightcolSb);
            sb.append("</div>");
            sb.append("</div>");
        }
        else if (!hasLeftContent && !hasRightContent)
        {
            sb.append(createEmptyContent());
        }
        else
        {
            sb.append(leftcolSb);
            sb.append(rightcolSb);
        }

    }

    /**
     * Create content for when there ae no fragments shown.
     *
     * @return the html for the empty content.
     */
    public String createEmptyContent()
    {
        return moduleDescriptor.getI18nBean().getText("browseproject.empty.tab.generic");
    }

    private boolean createColumnContent(C ctx, StringBuilder sb, List<F> columnFragments)
    {
        boolean hasAtleastOneFrag = false;
        for (F fragment : columnFragments)
        {
            hasAtleastOneFrag = appendFragmentIfVisible(ctx, sb, fragment) || hasAtleastOneFrag;
        }
        return hasAtleastOneFrag;
    }


    /**
     * Appends the raw HTML of the fragment to an output buffer, if the fragment should be displayed.
     *
     * @param ctx      the browse context
     * @param sb       the buffer to append to
     * @param fragment the fragment to display
     * @return true if the fragment was shown, false otherwise
     */
    private boolean appendFragmentIfVisible(final C ctx, final StringBuilder sb, final F fragment)
    {
        if (fragment.showFragment(ctx))
        {
            sb.append("<div class=\"module\" id=\"frag").append(fragment.getId()).append("\">");
            sb.append(fragment.getHtml(ctx));
            sb.append("</div>");
            return true;
        }
        return false;
    }

    /**
     * @param ctx the browse context
     * @return a list of fragments to be displayed at the top of the project tab panel, below the heading and above
     * the left and right columns
     */
    protected List<F> getTopFragments(C ctx)
    {
        return Collections.emptyList();
    }

    /**
     * @param ctx the browse context
     * @return a list of fragments to be displayed in the left column of the project tab panel
     */
    protected abstract List<F> getLeftColumnFragments(C ctx);

    /**
     * @param ctx the browse context
     * @return a list of fragments to be displayed in the right column of the project tab panel
     */
    protected abstract List<F> getRightColumnFragments(C ctx);

    /**
     * @return a list of fragments to be displayed in the menu section of the panel
     */

    public boolean showPanel(final C context)
    {
        // TODO: Check is there are any components in this project as well

        return !(getLeftColumnFragments(context).isEmpty() && getRightColumnFragments(context).isEmpty());
    }
}